package org.cainiao.api.lark.springboot;

import org.cainiao.api.lark.imperative.LarkApi;
import org.cainiao.api.lark.imperative.LarkApiWithAccessToken;
import org.cainiao.api.lark.imperative.LarkApiWithAppAccessToken;
import org.cainiao.api.lark.imperative.LarkApiWithOutAccessToken;
import org.cainiao.api.lark.imperative.authenticateandauthorize.AuthenticateAndAuthorize;
import org.cainiao.api.lark.imperative.authenticateandauthorize.getaccesstokens.restoperations.GetAccessTokensWithAppAccessToken;
import org.cainiao.api.lark.imperative.authenticateandauthorize.getaccesstokens.restoperations.GetAccessTokensWithOutAccessToken;
import org.cainiao.api.lark.imperative.docs.Docs;
import org.cainiao.api.lark.imperative.docs.board.thumbnail.Thumbnail;
import org.cainiao.api.lark.imperative.docs.docs.apireference.document.Document;
import org.cainiao.api.lark.imperative.docs.space.folder.Folder;
import org.cainiao.api.lark.impl.imperative.WebClientLarkApiFactory;
import org.cainiao.api.lark.impl.util.provider.LarkAccessTokenProvider;
import org.cainiao.api.lark.impl.util.provider.LarkAppAccessTokenProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;

import static org.cainiao.api.lark.impl.imperative.WebClientLarkApiFactory.DEFAULT_ACCESS_TOKEN_PROVIDER;
import static org.cainiao.api.lark.impl.imperative.WebClientLarkApiFactory.DEFAULT_APP_ACCESS_TOKEN_PROVIDER;

/**
 * <br />
 * <p>
 * Author: Cai Niao(wdhlzd@163.com)<br />
 */
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({WebClientLarkApiFactory.class})
@ConditionalOnBean({WebClient.class})
public class CNWebClientImperativeApiLarkConfiguration {

    @Bean
    @ConditionalOnMissingBean({WebClientLarkApiFactory.class})
    WebClientLarkApiFactory cnWebClientLarkApiFactory(WebClient webClient) {
        return WebClientLarkApiFactory.builder()
            .webClient(webClient)
            .baseUrl("https://open.feishu.cn/open-apis")
            .build();
    }

    @Bean
    @ConditionalOnMissingBean({LarkAccessTokenProvider.class})
    LarkAccessTokenProvider cnLarkAccessTokenProvider() {
        return DEFAULT_ACCESS_TOKEN_PROVIDER;
    }

    @Bean
    @ConditionalOnMissingBean({LarkAppAccessTokenProvider.class})
    LarkAppAccessTokenProvider cnLarkAppAccessTokenProvider() {
        return DEFAULT_APP_ACCESS_TOKEN_PROVIDER;
    }

    @Bean
    @ConditionalOnMissingBean({GetAccessTokensWithAppAccessToken.class})
    GetAccessTokensWithAppAccessToken cnLarkApiGetAccessTokensWithAppAccessToken(
        WebClientLarkApiFactory cnWebClientLarkApiFactory, LarkAppAccessTokenProvider cnLarkAppAccessTokenProvider) {

        return cnWebClientLarkApiFactory.getGetAccessTokensWithAppAccessToken(cnLarkAppAccessTokenProvider);
    }

    @Bean
    @ConditionalOnMissingBean({Document.class})
    Document cnLarkApiDocument(WebClientLarkApiFactory cnWebClientLarkApiFactory,
                               LarkAccessTokenProvider cnLarkAccessTokenProvider) {
        return cnWebClientLarkApiFactory.getDocument(cnLarkAccessTokenProvider);
    }

    @Bean
    @ConditionalOnMissingBean({Folder.class})
    Folder cnLarkApiFolder(WebClientLarkApiFactory cnWebClientLarkApiFactory,
                           LarkAccessTokenProvider cnLarkAccessTokenProvider) {
        return cnWebClientLarkApiFactory.getFolder(cnLarkAccessTokenProvider);
    }

    @Bean
    @ConditionalOnMissingBean({Thumbnail.class})
    Thumbnail cnLarkApiThumbnail(WebClientLarkApiFactory cnWebClientLarkApiFactory,
                                 LarkAccessTokenProvider cnLarkAccessTokenProvider) {
        return cnWebClientLarkApiFactory.getThumbnail(cnLarkAccessTokenProvider);
    }

    @Bean
    @ConditionalOnMissingBean({Docs.class})
    Docs cnLarkApiDocs(WebClientLarkApiFactory cnWebClientLarkApiFactory,
                       Folder cnLarkApiFolder, Document cnLarkApiDocument, Thumbnail cnLarkApiThumbnail) {
        return cnWebClientLarkApiFactory.getDocs(cnLarkApiFolder, cnLarkApiDocument, cnLarkApiThumbnail);
    }

    @Bean
    @ConditionalOnMissingBean({GetAccessTokensWithOutAccessToken.class})
    GetAccessTokensWithOutAccessToken cnLarkApiGetAccessTokensWithOutAccessToken(
        WebClientLarkApiFactory cnWebClientLarkApiFactory) {

        return cnWebClientLarkApiFactory.getGetAccessTokensWithOutAccessToken();
    }

    @Bean
    @ConditionalOnMissingBean({AuthenticateAndAuthorize.class})
    AuthenticateAndAuthorize cnLarkApiAuthenticateAndAuthorize(
        WebClientLarkApiFactory cnWebClientLarkApiFactory,
        GetAccessTokensWithAppAccessToken cnLarkApiGetAccessTokensWithAppAccessToken,
        GetAccessTokensWithOutAccessToken cnLarkApiGetAccessTokensWithOutAccessToken) {

        return cnWebClientLarkApiFactory
            .getAuthenticateAndAuthorize(cnLarkApiGetAccessTokensWithAppAccessToken, cnLarkApiGetAccessTokensWithOutAccessToken);
    }

    @Bean
    @ConditionalOnMissingBean({LarkApiWithAppAccessToken.class})
    LarkApiWithAppAccessToken cnLarkApiWithAppAccessToken(
        WebClientLarkApiFactory cnWebClientLarkApiFactory,
        GetAccessTokensWithAppAccessToken cnLarkApiGetAccessTokensWithAppAccessToken) {

        return cnWebClientLarkApiFactory.getLarkApiWithAppAccessToken(cnLarkApiGetAccessTokensWithAppAccessToken);
    }

    @Bean
    @ConditionalOnMissingBean({LarkApiWithAccessToken.class})
    LarkApiWithAccessToken cnLarkApiWithAccessToken(WebClientLarkApiFactory cnWebClientLarkApiFactory, Docs cnLarkApiDocs) {
        return cnWebClientLarkApiFactory.getLarkApiWithAccessToken(cnLarkApiDocs);
    }

    @Bean
    @ConditionalOnMissingBean({LarkApiWithOutAccessToken.class})
    LarkApiWithOutAccessToken cnLarkApiWithOutAccessToken(
        WebClientLarkApiFactory cnWebClientLarkApiFactory,
        GetAccessTokensWithOutAccessToken cnLarkApiGetAccessTokensWithOutAccessToken) {

        return cnWebClientLarkApiFactory.getLarkApiWithOutAccessToken(cnLarkApiGetAccessTokensWithOutAccessToken);
    }

    @Bean
    @ConditionalOnMissingBean({LarkApi.class})
    LarkApi cnLarkApi(WebClientLarkApiFactory cnWebClientLarkApiFactory,
                      AuthenticateAndAuthorize cnLarkApiAuthenticateAndAuthorize, Docs cnLarkApiDocs) {
        return cnWebClientLarkApiFactory.getLarkApi(cnLarkApiAuthenticateAndAuthorize, cnLarkApiDocs);
    }
}
